//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.UIDesigner
{
    #region using directives
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using System.Collections.ObjectModel;
    using Microsoft.Research.eResearch.Common.Eventing;
    #endregion

    /// <summary>
    /// Interaction logic for CategoryPicker.xaml
    /// </summary>
    public partial class CategoryPicker : UserControl
    {
        #region constructors
        public CategoryPicker()
        {
            InitializeComponent();
            this.workflowActivityTree.Tag = false;
            this.brdrHeader.MouseLeftButtonDown += (sender, e) =>
            {
                if (this.HeaderDrag != null)
                    this.HeaderDrag.Invoke(sender, e);
            };

            this.workflowActivityTree.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(WorkflowActivityTree_SelectedItemChanged);
            this.workflowActivityTree.PreviewKeyDown += new KeyEventHandler(WorkflowActivityTree_PreviewKeyDown);
            this.Focusable = false;
            this.GotFocus += new RoutedEventHandler(CategoryPicker_GotFocus);
        }

        private void CategoryPicker_GotFocus(object sender, RoutedEventArgs e)
        {
            //if (this.workflowActivityTree.Items.Count > 0)
            //{
            //    TreeViewItem item = this.workflowActivityTree.Items[0] as TreeViewItem;
            //    item.Focus();
            //}
        }

        public event EventHandler CategorySelectedEvent;

        public event EventHandler CategoryPickerCancel;

        public event EventHandler CategoryPickerOk;

        public CategoryPicker(Collection<WorkflowCategoryModel> workflowCategories)
            : this()
        {
            if (workflowCategories == null)
            {
                throw new ArgumentNullException("workflowCategories");
            }

            CreateWfCategoryTree(workflowCategories);
        }

        #endregion

        /// <summary>
        /// Return the selected category model.
        /// </summary>
        public WorkflowCategoryModel SelectedModel
        {
            get
            {
                bool cancelled = false;
                if (this.workflowActivityTree.Tag != null)
                {
                    if (!bool.TryParse(this.workflowActivityTree.Tag.ToString(), out cancelled))
                    {
                        cancelled = false;
                    }
                }

                if (this.workflowActivityTree.SelectedItem != null && !cancelled)
                {
                    TreeViewItem selectedItem = this.workflowActivityTree.SelectedItem as TreeViewItem;
                    return selectedItem.DataContext as WorkflowCategoryModel;
                }
                else
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// Occurs when header drag.
        /// </summary>
        public event EventHandler HeaderDrag;

        #region Private methods

        /// <summary>
        /// Event handler for the selected item changed event.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WorkflowActivityTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            this.workflowActivityTree.Tag = false;
            if (CategorySelectedEvent != null)
            {
                CategorySelectedEvent.Invoke(sender, e);
            }
        }

        /// <summary>
        /// Create a category tree from the category list given.
        /// </summary>
        /// <param name="workflowCategories">The workflow category list provided.</param>
        private void CreateWfCategoryTree(Collection<WorkflowCategoryModel> workflowCategories)
        {
            // Create the first level of categories in tree.
            for (int categoryCounter = 0; categoryCounter < workflowCategories.Count; categoryCounter++)
            {
                WorkflowCategoryModel objCategory = workflowCategories[categoryCounter];
                TreeViewItem parentNode = this.BuildCategoryNode(objCategory);
                parentNode.GotFocus += new RoutedEventHandler(parentNode_GotFocus);
                this.workflowActivityTree.Items.Add(parentNode);
            }
        }

        private void parentNode_GotFocus(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
        }

        /// <summary>
        /// Builds the Category Node fo the given WorkflowCategoryModel
        /// </summary>
        /// <param name="category">ActivityCategoryModel</param>
        /// <returns>TreeViewItem</returns>
        private TreeViewItem BuildCategoryNode(WorkflowCategoryModel category)
        {
            // Create a new category node.
            TreeViewItem categoryParentNode = new TreeViewItem();
            categoryParentNode.Header = category.Label;
            categoryParentNode.DataContext = category;
            categoryParentNode.Style = (Style)TryFindResource(UIDesignerCodeConstants.CATEGORYPICKERTREEITEMSTYLE);

            // Iterate through the sub categories and build a tree for them.
            for (int categoryCounter = 0; categoryCounter < category.Categories.Count; categoryCounter++)
            {
                TreeViewItem categoryChild = this.BuildCategoryNode(category.Categories[categoryCounter]);
                categoryParentNode.Items.Add(categoryChild);
            }

            // the node created.
            return categoryParentNode;
        }

        /// <summary>
        /// Handles the keydown event on the workflow tree. Expands the node on enter.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WorkflowActivityTree_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                if(this.workflowActivityTree.SelectedItem != null)
                {
                    TreeViewItem selectedItem = this.workflowActivityTree.SelectedItem as TreeViewItem;
                    if (selectedItem.Items.Count > 0)
                    {
                        if (selectedItem.IsExpanded)
                        {
                            selectedItem.IsExpanded = false;
                        }
                        else
                        {
                            selectedItem.IsExpanded = true;
                        }
                        e.Handled = true;
                    }
                }            
            }     
        }

        private void OnOkClick(object sender, RoutedEventArgs e)
        {
            this.workflowActivityTree.Tag = false;
            if (this.CategoryPickerOk != null)
            {
                this.CategoryPickerOk.Invoke(sender, new EventArgs());
            }
        }

        private void OnCancelClick(object sender, RoutedEventArgs e)
        {
            this.workflowActivityTree.Tag = true;
            if (this.CategoryPickerCancel != null)
            {
                this.CategoryPickerCancel.Invoke(sender, new EventArgs());
            }
        }

        #endregion
    }
}
